package com.tg.base.concurrent.lock.reentrantLock;

import com.google.common.collect.Lists;

import java.util.ArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 验证reentrantLock的可中断机制
 *
 * 当采用lockInterrupt()方法，输出如下，f2任务被取消
 * -----------------------------------
 * 开始上锁:f1
 * 开始上锁:f2
 * f2取消
 * 结束上锁:f1
 * ------------------------------------
 *
 * 当采用lock()方法，输出如下，f2任务不能被取消
 * -----------------------------------
 * 开始上锁:f2
 * 开始上锁:f1
 * f2取消
 * 结束上锁:f2
 * 结束上锁:f1
 * ------------------------------------
 */
public class ReentrantLockInterrupt {


    private static Lock lock1 = new ReentrantLock();

    /**
     * 控制使用lock
     */
    private static boolean beLockInterrupt = true;

    public static void main(String[] args) throws InterruptedException {

        FutureTask f1 = build("f1", beLockInterrupt);
        FutureTask f2 = build("f2", beLockInterrupt);

        Executor executorService = Executors.newFixedThreadPool(3);
        executorService.execute(f1);
        executorService.execute(f2);

        TimeUnit.SECONDS.sleep(3);

        f2.cancel(true);
        System.out.println("f2取消");
    }

    private static FutureTask build(final String name, boolean lockInterrupt) {
        return new FutureTask(() -> {
            try {
                System.out.println("开始上锁:" + name);
                if (lockInterrupt) {
                    lock1.lockInterruptibly();
                } else {
                    lock1.lock();
                }
                slowAction();
            } finally {
                lock1.unlock();
                System.out.println("结束上锁:" + name);
            }
            return 0;
        });
    }

    /**
     * 慢操作，同时
     */
    private static int slowAction() {
        ArrayList<Integer> objects = Lists.newArrayList();
        ArrayList<Integer> results = Lists.newArrayList();

        for (int i = 0; i < 100000; i++) {
            objects.add(i);
            int t = 5 * i;
            if (objects.contains(t)) {
                results.add(t);
            }
        }
        return 0;
    }
}
